package com.wing.productionPlan.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wing.common.utils.CodeUtil;
import com.wing.productionPlan.dao.DynamicDao;
import com.wing.productionPlan.dao.ProductionTheWorkOrderDao;
import com.wing.productionPlan.model.entity.ProductionTheWorkOrder;
import com.wing.productionPlan.model.entity.ProductionWorkOrder;
import com.wing.productionPlan.model.request.ProductionTheWorkOrderForm;
import com.wing.productionPlan.model.response.*;
import com.wing.web.db.config.util.DynamicDataSource;
import com.wing.web.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 生产报工单-ServiceImpl
 *
 * @author
 */
@Service
@Slf4j
public class ProductionTheWorkOrderServiceImpl extends ServiceImpl<ProductionTheWorkOrderDao, ProductionTheWorkOrder> implements ProductionTheWorkOrderService {

    @Autowired
    private QualityTestingRecordDetailService qualityTestingRecordDetailService;
    @Autowired
    private ProductionWorkOrderService productionWorkOrderService;
    @Autowired
    private DynamicDao dynamicDao;
    @Autowired
    private ProductionPlanService productionPlanService;
    @Autowired
    private ProductionPieceRateDetailService pieceRateDetailService;

    @Transactional
    @Override
    public void add(ProductionTheWorkOrderForm productionTheWorkOrderForm) {
        //校验
        ProductionTheWorkOrder productionTheWorkOrder = new ProductionTheWorkOrder();
        ProductionWorkOrder workOrder = productionWorkOrderService.getById(productionTheWorkOrderForm.getWorkOrderId());
        CopyOptions copyOptions = CopyOptions.create()
                .setEditable(ProductionTheWorkOrder.class)
                .setIgnoreError(true)
                .setIgnoreNullValue(true);
        BeanUtil.copyProperties(productionTheWorkOrderForm, productionTheWorkOrder, copyOptions);
        String today = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
        Integer maxNo = dynamicDao.getDayMaxNo("ord_production_the_work_order");
        String code = CodeUtil.getCode(maxNo);
        productionTheWorkOrder.setCode("BG" + today + code);
        productionTheWorkOrder.setNo(Integer.valueOf(code));
        productionTheWorkOrder.setDay(Integer.valueOf(today));
        productionTheWorkOrder.setDeviceModel(productionTheWorkOrderForm.getDeviceType());
        productionTheWorkOrder.setProductionPlanId(workOrder.getProductionPlanId());
        productionTheWorkOrder.setCreatorName(JwtUtils.getLoginUsername());
        productionTheWorkOrder.setStatus(ProductionTheWorkOrder.Status.confirm);
        baseMapper.insert(productionTheWorkOrder);

//        //查询工单已经报工的合格数
//        Integer workOrderQualifiedSum = baseMapper.getWorkOrderQualifiedSum(workOrder.getId());
//        //工单已经报工的合格数大于等于工单的生产数修改工单状态
//        if(workOrderQualifiedSum >= workOrder.getProductionQuantity()){
//            workOrder.setStatus(ProductionWorkOrder.Status.accomplish);
//            productionWorkOrderService.updateById(workOrder);
//        }
//        if(workOrder.getProductionPlanId() != null){
//            ProductionPlan productionPlan = productionPlanService.getById(workOrder.getProductionPlanId());
//            Integer planQualifiedSum = baseMapper.getPlanQualifiedSum(productionPlan.getId());
//            //计划下报工单的合格总数大于等于计划生产数修改计划状态
//            if(planQualifiedSum >= productionPlan.getProductionQuantity()){
//                productionPlan.setStatus(ProductionPlan.Status.accomplish);
//                productionPlanService.updateById(productionPlan);
//            }
//        }
    }

    @Override
    public List<ProductionTheWorkOrderVO> list4app(Map<String, Object> params) {
        return baseMapper.list4app(params);
    }

    @Override
    public Page<ProductionTheWorkOrderVO> pageList4app(Page page, Map<String, Object> params) {
        List<ProductionTheWorkOrderVO> list = baseMapper.list4app(page, params);
        page.setRecords(list);
        return page;
    }

    @Override
    public ProductionTheWorkOrderVO get4appById(Long id) {
        return baseMapper.get4appById(id);
    }

    @Override
    public IPage<ProductionTheWorkOrderVO> getProductionTheWorkOrderVOPageList(ProductionTheWorkOrderVO productionTheWorkOrderVO, Integer page, Integer limit) {
        IPage<ProductionTheWorkOrderVO> iPage = new Page<>(page, limit);
        QueryWrapper<ProductionTheWorkOrder> wrapper = new QueryWrapper<>();
        if (productionTheWorkOrderVO.getProcessId() != null) {
            wrapper.eq("w.process_id", productionTheWorkOrderVO.getProcessId());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getCode())) {
            wrapper.and(qw -> qw.like("wo.code", productionTheWorkOrderVO.getCode()));
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getWorkOrderCode())) {
            wrapper.and(qw -> qw.like("w.code", productionTheWorkOrderVO.getWorkOrderCode()));
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getSkuName())) {
            wrapper.and(qw -> qw.like("w.sku_name", productionTheWorkOrderVO.getSkuName()));
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getSkuCode())) {
            wrapper.and(qw -> qw.like("w.sku_code", productionTheWorkOrderVO.getSkuCode()));
        }
        if (productionTheWorkOrderVO.getStatus() != null) {
            wrapper.eq("wo.status", productionTheWorkOrderVO.getStatus().getValue());
        }
        if (productionTheWorkOrderVO.getWorkOrderId() != null) {
            wrapper.eq("wo.work_order_id", productionTheWorkOrderVO.getWorkOrderId());
        }
        if (productionTheWorkOrderVO.getCreator() != null) {
            wrapper.eq("wo.creator", productionTheWorkOrderVO.getCreator());
        }
        if (productionTheWorkOrderVO.getQualityType() != null) {
            wrapper.eq("w.quality_type", productionTheWorkOrderVO.getQualityType());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getProcessName2())) {
            wrapper.like("wo.process_name", productionTheWorkOrderVO.getProcessName2());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getType())) {
            wrapper.apply("w.process_id in (select id from ord_production_process where process_id in (select id from res_benchmark_book_echnology where type like CONCAT('%',{0},'%')))", productionTheWorkOrderVO.getType());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getWorkshopName())) {
            wrapper.like("wo.workshop_name", productionTheWorkOrderVO.getWorkshopName());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getQualityAttributes())) {
            if ("0".equals(productionTheWorkOrderVO.getQualityAttributes())) {
                productionTheWorkOrderVO.setQualityAttributes("");
            }
            wrapper.apply("w.process_id in (select id from ord_production_process where process_id in (select id from res_benchmark_book_echnology where quality_attributes = {0}))", productionTheWorkOrderVO.getQualityAttributes());
        }
        if (StringUtils.isNotEmpty(productionTheWorkOrderVO.getCreatorName())) {
            wrapper.like("wo.creator_name", productionTheWorkOrderVO.getCreatorName());
        }
        if (ObjectUtil.isNotNull(productionTheWorkOrderVO.getProductionPlanId())) {
            wrapper.like("wo.production_plan_id", productionTheWorkOrderVO.getProductionPlanId());
        }
        if (ObjectUtil.isNotNull(productionTheWorkOrderVO.getStatusRange())) {
            wrapper.ge("wo.status", productionTheWorkOrderVO.getStatusRange());
        }
        if (ObjectUtil.isNotEmpty(productionTheWorkOrderVO.getProductTypeName())) {
            wrapper.like("p.product_type_name", productionTheWorkOrderVO.getProductTypeName());
        }
        if (ObjectUtil.isNotEmpty(productionTheWorkOrderVO.getCreateTimeStart())) {
            wrapper.ge("wo.create_time", productionTheWorkOrderVO.getCreateTimeStart());
        }
        if (ObjectUtil.isNotEmpty(productionTheWorkOrderVO.getCreateTimeEnd())) {
            wrapper.le("wo.create_time", productionTheWorkOrderVO.getCreateTimeEnd());
        }

        if (StrUtil.isNotEmpty(productionTheWorkOrderVO.getKeyword())) {
            wrapper.like("ppd.sku_name", productionTheWorkOrderVO.getKeyword())
                    .or().like("ppd.sku_spec", productionTheWorkOrderVO.getKeyword())
                    .or().like("ppd.sku_code", productionTheWorkOrderVO.getKeyword())
                    .or().like("w.process_name", productionTheWorkOrderVO.getKeyword())
                    .or().like("w.`code`", productionTheWorkOrderVO.getKeyword())
                    .or().like("wo.`code`", productionTheWorkOrderVO.getKeyword());
        }
        wrapper.orderByDesc("wo.create_time");

        Map<String, Object> params = new HashMap<String, Object>();
        String databaseUser = DynamicDataSource.USER_PREFIX;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(DynamicDataSource.name.get())) {
            databaseUser = databaseUser + "-" + DynamicDataSource.name.get();
        }
        params.put("databaseUser", databaseUser);

        baseMapper.getProductionTheWorkOrderVOPageList(iPage, params, wrapper);
        return iPage;
    }

    @Override
    public ProductionTheWorkOrderVO selectTheWorkOrderInfo(Long id) {
        ProductionTheWorkOrderVO theWorkOrderVO = baseMapper.selectTheWorkOrderInfo(id);
        Map<String, Object> map = qualityTestingRecordDetailService.getProcessOutputAndYield(theWorkOrderVO.getProcessId(), null);
        theWorkOrderVO.setYield(map.get("yield").toString());
        return theWorkOrderVO;
    }

    /**
     * 查询报工单详情
     *
     * @param id
     * @return
     */
    @Override
    public ProductionTheWorkOrderSearchVO getDetailBy(Long id) {
        return this.baseMapper.getDetailBy(id);
    }

    /**
     * 审核
     *
     * @param id
     * @param status
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean audit(Long id, String status) {
        ProductionTheWorkOrder productionTheWorkOrder = baseMapper.selectById(id);
        if ("correspond".equals(status)) {
            //0 修改状态
            productionTheWorkOrder.setCheckStatus(ProductionTheWorkOrder.CheckStatus.correspond);
            productionTheWorkOrder.setStatus(ProductionTheWorkOrder.Status.checked);

            //相符 需要添加报工数
            ProductionWorkOrder byId = this.productionWorkOrderService.getById(productionTheWorkOrder.getWorkOrderId());
            if (ObjectUtil.isNotEmpty(byId)) {
                byId.setReportedQuantity(byId.getReportedQuantity() + productionTheWorkOrder.getWorkQuantity());
                byId.setUpdateTime(LocalDateTime.now());
                byId.setModifier(JwtUtils.getLoginUserId());
                //设置可领用数 = 当前可领用 + 报工数
                int canGetQuantity = byId.getCanGetQuantity() == null ? 0 : byId.getCanGetQuantity();
                byId.setCanGetQuantity(canGetQuantity + productionTheWorkOrder.getWorkQuantity() -productionTheWorkOrder.getQualifiedNoQuantity());
                byId.setModifierName(JwtUtils.getLoginUsername());

                //2.修改开工单 不合格数
                //计算不合格数
                int noQuantity = byId.getAcceptanceNoQuantity() == null ? 0 : byId.getAcceptanceNoQuantity();
                byId.setAcceptanceNoQuantity(noQuantity + productionTheWorkOrder.getQualifiedNoQuantity());
                this.productionWorkOrderService.updateById(byId);
            }
        } else if ("discrepancy".equals(status)) {
            //1
            productionTheWorkOrder.setCheckStatus(ProductionTheWorkOrder.CheckStatus.discrepancy);
            productionTheWorkOrder.setStatus(ProductionTheWorkOrder.Status.checked);
        } else if ("confirm".equals(status)) {
            productionTheWorkOrder.setStatus(ProductionTheWorkOrder.Status.confirmed);
            //创建计件工资明细
            ProductionWorkOrder workOrder = this.productionWorkOrderService.getById(productionTheWorkOrder.getWorkOrderId());//开工单数据
            pieceRateDetailService.create(productionTheWorkOrder, workOrder);

//            //更新计件工资明细状态
//            UpdateWrapper<ProductionPieceRateDetail> updateWrapper = new UpdateWrapper();
//            updateWrapper.set("status", PieceRateDetailStatusEnum.CONFIRMED.getCode());
//            updateWrapper.set("confirm_time", DateUtil.date());
//            updateWrapper.eq("the_work_order_id", productionTheWorkOrder.getId());
//            pieceRateDetailService.update(updateWrapper);
        }

        productionTheWorkOrder.setUpdateTime(LocalDateTime.now());
        productionTheWorkOrder.setModifier(JwtUtils.getLoginUserId());
        productionTheWorkOrder.setModifierName(JwtUtils.getLoginUsername());
        return this.baseMapper.updateById(productionTheWorkOrder) > 0;
    }

    /**
     * 查询送检 报工总数量
     *
     * @param id
     * @return
     */
    @Override
    public WorkOrderSendTotallVO getTotalBy(Long id) {
        return baseMapper.getTotalBy(id);
    }

    @Override
    public ProcessCardInfoVo getCardInfoBy(Long id) {
        return this.baseMapper.getCardInfoBy(id);
    }


    /**
     * 查询开工单打印信息
     *
     * @param id
     * @return
     */
    @Override
    public ProWorkOrderPrintVo getWorkOrderPrint(Long id) {
        return baseMapper.getWorkOrderPrint(id);
    }

    /**
     * 获取报工单打印信息
     *
     * @param id
     * @return
     */
    @Override
    public ProductionTheWorkPrintVO getPrintTheWork(Long id) {
        return baseMapper.getPrintTheWork(id);
    }
}
